package com.jcfk.eam.service.mould;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.jcfk.common.business.service.BaseService;
import com.jcfk.common.core.utils.BeanUtils;
import com.jcfk.common.security.utils.SecurityUtils;
import com.jcfk.common.web.domain.DataPage;
import com.jcfk.common.web.domain.RetResult;
import com.jcfk.eam.dao.mould.MouldBomDetailDao;
import com.jcfk.eam.domain.dto.mould.MouldBomDetailDTO;
import com.jcfk.eam.domain.po.mould.MouldBomDetail;
import com.jcfk.eam.domain.query.mould.MouldBomDetailQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static com.jcfk.common.core.utils.BeanUtils.convertList;

/**
 * 模具bom详情表
 *
 * @author yrl
 * @email 
 * @date 2024-11-08
 */
@Service
public class MouldBomDetailService extends BaseService<MouldBomDetailDao, MouldBomDetail> {

    /**
     * ModBomDetail分页查询
     *
     * @param page  分页设置
     * @param query 查询条件
     * @return 分页查询结果
     */
    public DataPage<MouldBomDetailDTO> queryByPage(DataPage<MouldBomDetailDTO> page, MouldBomDetailQuery query) {
        // 分页查询
        page = this.baseMapper.queryByPage(page, query);
        return page;
    }


        /**
     * 判断ModBomDetail是已经存在
     *
     * @param dto
     * @return
     */
    public RetResult<String> isValid(MouldBomDetailDTO dto) {
        QueryWrapper<MouldBomDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("deleted", 0);
                                                                    
        return RetResult.ok();
    }

    /**
     * 插入模具bom详情表
     *
     * @param dto 插入对象
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void insert(MouldBomDetailDTO dto) {

        // 保存
        MouldBomDetail item = new MouldBomDetail();
        BeanUtils.copyProperties(dto, item);
        this.setDefaultValue(item);

        super.save(item);
    }

    /**
     * 更新模具bom详情表
     *
     * @param dto 更新对象
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void update(MouldBomDetailDTO dto) {

        // 保存
        MouldBomDetail item = new MouldBomDetail();
        BeanUtils.copyProperties(dto, item);

        // 默认数据
        this.setDefaultValue(item);

        super.updateById(item);
    }

    /**
     * 根据批量主键删除模具bom详情表(逻辑删除)
     *
     * @param dto
     * @return bool
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean logicDeleteList(MouldBomDetailDTO dto) {

        MouldBomDetail item = new MouldBomDetail();

        this.setDefaultValue(item);
        item.setDeleted("1");

        QueryWrapper<MouldBomDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", dto.getIds());

        return this.update(item, queryWrapper);
    }

    /**
     * 设置添加默认值
     *
     * @param item 添加对象
     */
    public void setDefaultValue(MouldBomDetail item) {
        if (StrUtil.isEmpty(item.getCreatedUserId())) {
            item.setCreatedUserId(SecurityUtils.getUserId());
            item.setCreateTime(new Date());
                item.setDeleted("0");
                item.setEnabled("1");
                                                                                        item.setCreatedUserName(SecurityUtils.getUserName());
                                                                                                                                                        }
        item.setLastUpdatedUserId(SecurityUtils.getUserId());
        item.setLastUpdateTime(new Date());

                                        item.setLastUpdatedUserName(SecurityUtils.getUserName());
                                        
    }

    /**
     * 根据主键获取模具bom详情表信息
     *
     * @param id 主键
     * @return StandardCodeDTO
     */
    public MouldBomDetailDTO get(String id) {
        // 查询数据
        MouldBomDetail item = this.baseMapper.selectById(id);
            MouldBomDetailDTO dto = new MouldBomDetailDTO();
        try {
            BeanUtils.copyProperties(item, dto);
        } catch (RuntimeException e) {
            throw e;
        }

        return dto;
    }

            /**
         * 模具bom详情表批量保存
         *
         * @param dtos
         * @return StandardCodeDTO
         */
        @Transactional(rollbackFor = Exception.class)
        public void saveBatch(List<MouldBomDetailDTO> dtos, String  id) {

            dtos.forEach(detail -> detail.getDetails()
                    .forEach(child -> Assert.isTrue(CollUtil.isEmpty(child.getDetails()),"BOM最多支持两级")));

            // 删除所有旧数据
            MouldBomDetail mouldBomDetail = new MouldBomDetail();
            mouldBomDetail.setLastUpdatedUserId(SecurityUtils.getUserId());
            mouldBomDetail.setLastUpdateTime(new Date());
            mouldBomDetail.setLastUpdatedUserName(SecurityUtils.getUserName());
            mouldBomDetail.setDeleted("1");
            QueryWrapper<MouldBomDetail> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(MouldBomDetail::getBomId, id);
            this.update(mouldBomDetail,queryWrapper);

            List<MouldBomDetail> mouldBomDetails = convertTreeToList(dtos, "0",id);


            // 保存新增
            if (mouldBomDetails.size() > 0) this.saveBatch(mouldBomDetails);
        }

    private List<MouldBomDetail> convertTreeToList(List<MouldBomDetailDTO> dtos, String parentId, String bomId) {
        List<MouldBomDetail> results = new ArrayList<>();
        for (int i = 0; i < dtos.size(); i++) {
            MouldBomDetail item = new MouldBomDetail();
            BeanUtils.copyProperties(dtos.get(i), item);
            setDefaultValue(item);
            IdentifierGenerator identifierGenerator = new DefaultIdentifierGenerator();
            Number nextId = identifierGenerator.nextId(null);
            item.setId(nextId.toString());
            item.setParentId(parentId);
            item.setBomId(bomId);
            item.setSort(i+1);
            if (CollUtil.isNotEmpty(dtos.get(i).getDetails())) {
                results.addAll(convertTreeToList(dtos.get(i).getDetails(), item.getId(), bomId));
            }
            results.add(item);
        }
        return results;
    }


    /**
     * 根据条件获取单表信息列表
     *
     * @param query 查询条件
     * @return List<ModBomDetailDTO>
     */
    public List<MouldBomDetailDTO> getList(MouldBomDetailQuery query) {
        // 查询条件
        QueryWrapper<MouldBomDetail> qw = new QueryWrapper<>();
                                                                                                                                                                                                                                                                                                                            qw.lambda().eq(!StrUtil.isEmpty(query.getBomId()), MouldBomDetail::getBomId, query.getBomId());
                                                                                                                                                                                                                                                                        // 查询数据
        List<MouldBomDetail> list = super.list(qw);

        return convertList(list, MouldBomDetailDTO.class);
    }

    /**
     * 根据主键获取模具bom详情表信息
     *
     * @param id 主键
     * @return StandardCodeDTO
     */
    public void deleteItem(String id) {
            MouldBomDetail item = getById(id);
        this.setDefaultValue(item);
        item.setDeleted("1");

        this.updateById(item);
        }

    public List<MouldBomDetailDTO> queryTreeCopyByNum(String bomId) {
        Assert.notEmpty(bomId, "bomId不能为空");

        // 查询条件
        QueryWrapper<MouldBomDetail> qw = new QueryWrapper<>();
        qw.lambda().eq(MouldBomDetail::getBomId, bomId);
        qw.lambda().eq(MouldBomDetail::getDeleted, "0");

        // 查询数据
        List<MouldBomDetail> list = this.list(qw);
        List<MouldBomDetailDTO> mouldBomDetailDTOS = convertList(list, MouldBomDetailDTO.class);
        // map的意义是存储每个节点的id和数量，方便后面拼接
        Map<String, Integer> detailIdNumberMap = MapUtil.<String, Integer>builder().build();


        Map<String, MouldBomDetailDTO> parentMap = mouldBomDetailDTOS.stream().filter(detail -> detail.getParentId().equals("0"))
                .collect(Collectors.toMap(MouldBomDetailDTO::getId, Function.identity()));
        // 父节点每个物料数量
        Map<String, Integer> parentCountMap = mouldBomDetailDTOS.stream().filter(detail -> detail.getParentId().equals("0"))
                .collect(Collectors.groupingBy(MouldBomDetailDTO::getMaterialCode,
                        Collectors.reducing(0, MouldBomDetailDTO::getNumber, Integer::sum)));
        // 子节点每个物料数量
        Map<String, Integer> sunCountMap = mouldBomDetailDTOS.stream().filter(detail -> !detail.getParentId().equals("0"))
                .collect(Collectors.groupingBy(MouldBomDetailDTO::getMaterialCode,
                        Collectors.reducing(0, t -> t.getNumber() * parentMap.get(t.getParentId()).getNumber(), Integer::sum)));
        // 合并父节点和子节点的数量
        sunCountMap.forEach((key,value) -> parentCountMap.merge(key,value, Integer::sum));
        AtomicInteger sort = new AtomicInteger(1);
        return convertListToTree(mouldBomDetailDTOS,"0",detailIdNumberMap,parentCountMap,sort);
    }


    /**
     * list 转树形结构
     * @param details 转树形结构的数据
     * @param parentId 父节点id 最上层的id为0
     * @param detailIdNumberMap 存储每个节点的id和数量 方便拼接唯一display编码
     * @param materialCountMap materialCode的数量
     * @return 转树形结构
     */
    public List<MouldBomDetailDTO> convertListToTree(List<MouldBomDetailDTO> details, String parentId, Map<String, Integer> detailIdNumberMap, Map<String, Integer> materialCountMap, AtomicInteger sort) {
        return details.stream().filter(detail -> detail.getParentId().equals(parentId))
                .sorted(Comparator.comparing(MouldBomDetailDTO::getSort))
                // 循环次数
                .flatMap(detail -> IntStream.range(0, detail.getNumber())
                        .mapToObj(i -> {
                            MouldBomDetailDTO newDetail = new MouldBomDetailDTO();
                            BeanUtils.copyProperties(detail, newDetail);
                            newDetail.setSort(sort.getAndAdd(1));
                            // 递归构建子节点
                            newDetail.setDetails(convertListToTree(details.stream()
                                            .filter(d -> d.getParentId().equals(newDetail.getId()))
                                            .collect(Collectors.toList()),
                                    newDetail.getId(),detailIdNumberMap,materialCountMap,sort));
                            // 如果bom数量大于1  拼接数据
                            if (materialCountMap.get(newDetail.getMaterialCode()) > 1){
                                // 拼接带"_"的数据
                                int cumulativeQuantity = detailIdNumberMap.getOrDefault(detail.getMaterialCode(), 0) + 1;
                                newDetail.setDisplayCode(StrUtil.format("{}_{}",
                                        newDetail.getMaterialCode(), String.format("%03d", cumulativeQuantity)));
                                // 累加数量
                                detailIdNumberMap.put(detail.getMaterialCode(), cumulativeQuantity);
                            }else {
                                newDetail.setDisplayCode(newDetail.getMaterialCode());
                            }
                            return newDetail;
                        }))
                .collect(Collectors.toList());
    }
}

